home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 17
/
CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso
/
CUCD
/
Programming
/
DiceSource
/
src
/
dc1
/
exp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-09-09
|
7KB
|
337 lines
/*
* (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
* use is allowed under the terms of the DICE-LICENSE FILE,
* DICE-LICENSE.TXT.
*/
/*
* EXP.C
*/
#include "defs.h"
Prototype long ExpToConstant(Exp *);
Prototype Type *ExpToType(Exp *);
Prototype void ExpToLValue(Exp *, Stor *, Type *);
Prototype void InsertCast(Exp **, Type *);
Prototype void InsertNot(Exp **);
Prototype void InsertBranch(Exp **, long, long);
Prototype void InsertAssign(Exp **, Var *);
Prototype long AutoIncDecSize(Exp *);
long
ExpToConstant(exp)
Exp *exp;
{
long value;
short genPass = GenPass;
Assert(exp);
GenPass = 0;
(*exp->ex_Func)(&exp); /* last arg illegal ptr */
GenPass = genPass;
if (exp->ex_Stor.st_Type != ST_IntConst) {
yerror(exp->ex_LexIdx, EERROR_EXPECTED_INT_CONST);
return(0);
}
value = exp->ex_Stor.st_IntConst;
return(value);
}
Type *
ExpToType(exp)
Exp *exp;
{
short genPass = GenPass;
Assert(exp);
GenPass = 0;
(*exp->ex_Func)(&exp); /* last arg illegal ptr */
GenPass = genPass;
if (exp->ex_Type == NULL) {
yerror(exp->ex_LexIdx, EERROR_ILLEGAL_RETURN_TYPE);
return(&VoidType);
}
return(exp->ex_Type);
}
/*
* Convert an expression to an lvalue whos result type should be
* 'type'.
*/
void
ExpToLValue(exp, stor, type)
Exp *exp;
Stor *stor;
Type *type;
{
short genPass = GenPass;
Assert(exp);
#ifdef NOTDEF
/*
* Propogate const class for string constants
*/
if (exp->ex_Stor.st_Type == ST_StrConst && type->Id == TID_PTR) {
if (type->SubType->Flags & TF_CONST)
exp->ex_Flags |= EF_CONST;
}
#endif
GenPass = 0;
(*exp->ex_Func)(&exp);
GenPass = 1;
(*exp->ex_Func)(&exp);
GenPass = genPass;
*stor = exp->ex_Stor;
if (stor->st_Type == ST_IntConst || stor->st_Type == ST_StrConst || stor->st_Type == ST_FltConst) {
stor->st_Size = type->Size;
return;
}
if (exp->ex_Type->Id == TID_ARY) {
stor->st_Flags |= SF_LEA;
return;
}
if ((stor->st_Flags & SF_LEA) == 0)
yerror(exp->ex_LexIdx, EERROR_NOT_LVALUE);
if (stor->st_Type == ST_RelReg || stor->st_Type == ST_RelArg)
yerror(exp->ex_LexIdx, EERROR_NOT_LVALUE);
}
/*
* Casting (BEFORE pass 0)
*
* Note that an explicit (cast) does not call this routine, but goes
* directly to GenCast.
*/
void
InsertCast(pexp, type)
Exp **pexp;
Type *type;
{
Exp *exp;
Exp *e1 = *pexp;
Type *etype = e1->ex_Type;
Assert(etype);
if (etype->Id == TID_BITFIELD) /* force the cast */
goto force;
/*
* Conversions that require no modifications other then unsignedness,
* which is handled by other routines (example: GenVarRef checks for
* ex_Type changes)
*/
if (type->Size == etype->Size && etype->Id == type->Id && (type->Id == TID_INT || type->Id == TID_FLT)) {
e1->ex_Type = type;
return;
}
/*
* Integer Constant to (Integer | Pointer)
* Floating Constant to (Integer | Pointer)
*/
if (type->Id == TID_INT || type->Id == TID_PTR) {
if (e1->ex_Stor.st_Type == ST_IntConst) {
short sv = type->Size;
if (type->Flags & TF_UNSIGNED)
sv |= 256;
switch(sv) {
case 0:
e1->ex_Stor.st_IntConst = 0;
/* XXX */
break;
case 1:
e1->ex_Stor.st_IntConst = (long)(char)e1->ex_Stor.st_IntConst;
break;
case 2:
e1->ex_Stor.st_IntConst = (long)(short)e1->ex_Stor.st_IntConst;
break;
case 4:
break;
case 256:
/* XXX */
e1->ex_Stor.st_IntConst = 0;
break;
case 256|1:
e1->ex_Stor.st_IntConst = (long)(unsigned char)e1->ex_Stor.st_IntConst;
break;
case 256|2:
e1->ex_Stor.st_IntConst = (long)(unsigned short)e1->ex_Stor.st_IntConst;
break;
case 256|4:
break;
default:
dbprintf(("InsertCast: bad size const-cast: %ld\n",type->Size));
Assert(0);
break;
}
e1->ex_Type = type;
return;
}
/*
* Floating constant to integer
*
* e1->ex_StrConst e1->ex_StrLen
*/
if (e1->ex_Token == TokFltConst) {
AllocConstStor(&e1->ex_Stor, FPStrToInt(e1, e1->ex_Stor.st_FltConst, e1->ex_Stor.st_FltLen), type);
e1->ex_Token = TokIntConst;
e1->ex_Func = GenIntConst;
e1->ex_Type = type;
return;
}
}
/*
* Floating Constant to Floating (no chg)
* Integer Constant to Floating ??
*/
if (type->Id == TID_FLT) {
if (e1->ex_Stor.st_Type == ST_IntConst) {
e1->ex_Stor.st_FltConst = IntToFPStr(e1->ex_Stor.st_IntConst, e1->ex_Stor.st_Flags & SF_UNSIGNED, &e1->ex_Stor.st_FltLen);
e1->ex_Type = type;
e1->ex_Stor.st_Size = e1->ex_Type->Size;
e1->ex_Stor.st_Type = ST_FltConst;
e1->ex_Token = TokFltConst;
e1->ex_Func = GenFltConst;
return;
}
if (e1->ex_Token == TokFltConst) {
e1->ex_Type = type;
return;
}
}
force:
exp = AllocTmpStructure(Exp);
exp->ex_Next = e1->ex_Next;
exp->ex_LexIdx = e1->ex_LexIdx;
exp->ex_Func = GenCast;
exp->ex_ExpL = e1;
exp->ex_Type = type;
exp->ex_Flags= (e1->ex_Flags & EF_CALL) | EF_ICAST;
exp->ex_Token = TokCast;
*pexp = exp;
(*exp->ex_Func)(pexp);
}
/*
* InsertNot() (also used to insert general exp's)
*/
void
InsertNot(pexp)
Exp **pexp;
{
Exp *exp = AllocStructure(Exp);
Exp *e1 = *pexp;
exp->ex_Func = GenNot;
exp->ex_ExpL = e1;
exp->ex_LexIdx = e1->ex_LexIdx;
exp->ex_Flags = e1->ex_Flags & EF_CALL;
*pexp = exp;
}
/*
* insert branch on COND_T (1) or COND_F (-1). See GenBool() for the
* specific generation routine. In many cases conditionals can be 100%
* optimized.
*/
void
InsertBranch(pexp, cond, label)
Exp **pexp;
long cond;
long label;
{
Exp *exp;
Exp *e1 = *pexp;
exp = AllocStructure(Exp);
exp->ex_Func = GenCondBranch;
if (cond >= 0)
exp->ex_LabelT= label;
else
exp->ex_LabelF= label;
exp->ex_Cond = cond;
exp->ex_ExpL = e1;
exp->ex_LexIdx = e1->ex_LexIdx;
exp->ex_Flags= e1->ex_Flags & EF_CALL;
*pexp = exp;
}
/*
* Converts exp to var = exp
*/
void
InsertAssign(pexp, var)
Exp **pexp;
Var *var;
{
Exp *exp = AllocStructure(Exp);
Exp *evar = AllocStructure(Exp);
Exp *e1 = *pexp;
Assert(e1);
evar->ex_Func = GenVarRef;
evar->ex_Token = TokVarRef;
evar->ex_Symbol = var->Sym;
evar->ex_Var = var;
evar->ex_LexIdx = e1->ex_LexIdx;
if (e1->ex_Token == TokExpAssBlock)
exp->ex_Func = GenBracEq;
else
exp->ex_Func = GenEq;
exp->ex_ExpL = evar;
exp->ex_ExpR = e1;
exp->ex_LexIdx= (*pexp)->ex_LexIdx;
exp->ex_Flags = e1->ex_Flags & EF_CALL;
*pexp = exp;
}
/*
* Determine amount of increment/decrement.
*/
long
AutoIncDecSize(exp)
Exp *exp;
{
Type *type = exp->ex_Type;
Assert(type);
if (type->Id == TID_PTR)
return(type->SubType->Size);
if (type->Id == TID_INT)
return(1);
yerror(exp->ex_LexIdx, EERROR_NOT_LVALUE);
return(0);
}